package com.jinzhi.jzweb.service.impl.moduleConfig;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.jinzhi.common.base.CoreServiceImpl;
import com.jinzhi.common.utils.Result;
import com.jinzhi.jzweb.dao.CareStuSignUpComRealityDao;
import com.jinzhi.jzweb.dao.StuSignUpComDao;
import com.jinzhi.jzweb.domain.ExaminationBatchComDO;
import com.jinzhi.jzweb.domain.ExaminationResultsComDO;
import com.jinzhi.jzweb.domain.moduleConfig.CareStuSignUpComRealityDO;
import com.jinzhi.jzweb.domain.moduleConfig.EncipherDO;
import com.jinzhi.jzweb.pojo.StuSignUpTeamVo;
import com.jinzhi.jzweb.pojo.StuVo;
import com.jinzhi.jzweb.pojo.moduleConfig.ExaminationCostStatisticVo;
import com.jinzhi.jzweb.pojo.moduleConfig.NationVo;
import com.jinzhi.jzweb.pojo.moduleConfig.OperationVo;
import com.jinzhi.jzweb.pojo.moduleConfig.StuDecryptVo;
import com.jinzhi.jzweb.service.ExaminationBatchComService;
import com.jinzhi.jzweb.service.ExaminationResultsComService;
import com.jinzhi.jzweb.service.StuSignUpComService;
import com.jinzhi.jzweb.service.moduleConfig.CareStuSignUpComRealityService;
import com.jinzhi.jzweb.service.moduleConfig.EncipherService;
import com.jinzhi.jzweb.utils.EasyPoiUtil;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 
 * <pre>
 * 考生报名
 * </pre>
 * <small> 2023-05-05 08:52:02 | lance</small>
 */
@Service
public class CareStuSignUpComRealityServiceImpl extends CoreServiceImpl<CareStuSignUpComRealityDao, CareStuSignUpComRealityDO> implements CareStuSignUpComRealityService {


    @Override
    public List<StuSignUpTeamVo> sumTeamStuSignExam(String name) {
        return baseMapper.sumTeamStuSignExam( name);
    }

    @Override
    public List<StuSignUpTeamVo> sumOneStuSignExam(String name) {
        return baseMapper.sumOneStuSignExam(name);
    }

    private final ExaminationResultsComService examinationResultsComService;

    @Override
    public Integer MaxNum(Long cbatchId) {
        return baseMapper.MaxNum(cbatchId);
    }

    private final EncipherService encipherService;

    private final ExaminationBatchComService examinationBatchService;

    public CareStuSignUpComRealityServiceImpl(ExaminationResultsComService examinationResultsComService,EncipherService encipherService,ExaminationBatchComService examinationBatchService) {
        this.examinationResultsComService = examinationResultsComService;
        this.encipherService = encipherService;
        this.examinationBatchService = examinationBatchService;
    }

    @Override
    public Page<CareStuSignUpComRealityDO> getStuGignUpCom(Integer curr, Integer pageSize) {
        Page<CareStuSignUpComRealityDO> page = new Page<>(
                Optional.of(curr).orElse(1),
                Optional.of(pageSize).orElse(10));
        //查询全部考生信息
        List<CareStuSignUpComRealityDO> sign = selectList(new EntityWrapper<CareStuSignUpComRealityDO>());
        //获取考生三个赛场得分
        //根据学生id查询成绩
        ExaminationResultsComDO examinationResultsComDO = new ExaminationResultsComDO();
        sign.forEach(a ->{
            examinationResultsComDO.setStuSignId(a.getId());
            ExaminationResultsComDO rcd = examinationResultsComService.selectOne(examinationResultsComDO);
            if(rcd!=null) {

                Double a111 = ((rcd.getScoingb1() + rcd.getScoingb2() + rcd.getScoingb3())/3);
                a111 = a111 + (rcd.getTotalScore() *  0.3); //理论成绩
                BigDecimal a1 = new BigDecimal(a111);
                double a11 = a1.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                rcd.setScoreA(String.valueOf(a11));

                BigDecimal b1 = new BigDecimal(((rcd.getScore1() + rcd.getScore2() + rcd.getScore3())/3));
                double b11 = b1.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                rcd.setScoreB(String.valueOf(b11));

                BigDecimal c1 = new BigDecimal(((rcd.getScoingc1() + rcd.getScoingc2() + rcd.getScoingc3())/3));
                double c11 = c1.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                rcd.setScoreC(String.valueOf(c11));

                a.setScore(Double.valueOf(rcd.getScoreA())+Double.valueOf(rcd.getScoreB())+Double.valueOf(rcd.getScoreC()));
                a.setExaminationResultsComDO(rcd);
            }
        });
        sign = sign.stream().sorted(Comparator.comparing(CareStuSignUpComRealityDO::getScore,Comparator.nullsFirst(Double::compareTo)).reversed()).collect(Collectors.toList());
        page.setRecords(forDes(sign));
        return page;
    }

    public List<CareStuSignUpComRealityDO> forDes(List<CareStuSignUpComRealityDO> list1){
        if(list1.size()==0){
            return new ArrayList<>();
        }
        for (int i = 0; i < list1.size(); i++) {
            list1.get(i).setDes(i+1);
        }
        return list1;
    }



    @Override
    public void stuGignUpCom(HttpServletResponse response) {
        List<StuVo> stuVos = new ArrayList<>();
        //查询全部考生信息
        List<CareStuSignUpComRealityDO> sign = selectList(new EntityWrapper<CareStuSignUpComRealityDO>().eq("decrypt",1));
        //获取考生三个赛场得分
        //根据学生id查询成绩
        ExaminationResultsComDO examinationResultsComDO = new ExaminationResultsComDO();
        sign.forEach(a ->{
            StuVo stuVo = new StuVo();
            examinationResultsComDO.setStuSignId(a.getId());
            ExaminationResultsComDO rcd = examinationResultsComService.selectOne(examinationResultsComDO);
            if(rcd!=null) {

                Double a111 = ((rcd.getScoingb1() + rcd.getScoingb2() + rcd.getScoingb3())/3);
                a111 = a111 + (rcd.getTotalScore() *  0.3); //理论成绩
                BigDecimal a1 = new BigDecimal(a111);
                double a11 = a1.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                rcd.setScoreA(String.valueOf(a11));

                BigDecimal b1 = new BigDecimal(((rcd.getScore1() + rcd.getScore2() + rcd.getScore3())/3));
                double b11 = b1.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                rcd.setScoreB(String.valueOf(b11));

                BigDecimal c1 = new BigDecimal(((rcd.getScoingc1() + rcd.getScoingc2() + rcd.getScoingc3())/3));
                double c11 = c1.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                rcd.setScoreC(String.valueOf(c11));

                a.setScore(Double.valueOf(rcd.getScoreA())+Double.valueOf(rcd.getScoreB())+Double.valueOf(rcd.getScoreC()));
                a.setExaminationResultsComDO(rcd);

                stuVo.setScoreA(String.valueOf(a11));
                stuVo.setScoreB(String.valueOf(b11));
                stuVo.setScoreC(String.valueOf(c11));
            }
            stuVo.setNum2(a.getNum2());
            stuVo.setRealityUm2(a.getCandidateNumber());
            stuVo.setName(a.getName());
            stuVo.setIdNumber(a.getIdNumber());
            stuVo.setUnitName(a.getUnitName());
            stuVo.setTeacher(a.getTeacher());
            stuVo.setComNums(a.getComNums());
            stuVos.add(stuVo);

        });
        sign.stream().sorted(Comparator.comparing(CareStuSignUpComRealityDO::getScore,Comparator.nullsFirst(Double::compareTo)).reversed()).collect(Collectors.toList());
        //导出操作
        EasyPoiUtil.exportExcel(stuVos, "选手解密导出", "选手解密导出", StuVo.class, "选手解密导出", response);
    }

    /**
     * 生成二次加密好
     */
    @Override
    public void touchSign() {
        Wrapper<CareStuSignUpComRealityDO> wrapper1 = new EntityWrapper<CareStuSignUpComRealityDO>().eq("competition_type", 1);
        List<CareStuSignUpComRealityDO> signList1 = this.selectList(wrapper1);
        if(null!=signList1 && !signList1.isEmpty()){
            int i = 1;
            for (CareStuSignUpComRealityDO stuSignUpComDO : signList1) {
                Random random = new Random();
                stuSignUpComDO.setRandomCipher(String.valueOf(random.nextInt(900000)+100000));
                stuSignUpComDO.setDecrypt(0);
                if(i<10){
                    stuSignUpComDO.setNum2("A0"+i);
                }else{
                    stuSignUpComDO.setNum2("A"+i);
                }
                i++;
            }
            this.updateBatchById(signList1);
        }

        Wrapper<CareStuSignUpComRealityDO> wrapper2 = new EntityWrapper<CareStuSignUpComRealityDO>().eq("competition_type", 2);
        List<CareStuSignUpComRealityDO> signList2 = this.selectList(wrapper2);
        if(null!=signList2 && !signList2.isEmpty()){
            int i = 1;
            for (CareStuSignUpComRealityDO stuSignUpComDO : signList2) {
                Random random = new Random();
                stuSignUpComDO.setRandomCipher(String.valueOf(random.nextInt(900000)+100000));
                stuSignUpComDO.setDecrypt(0);
                if(i<10){
                    stuSignUpComDO.setNum2("A0"+i);
                }else{
                    stuSignUpComDO.setNum2("A"+i);
                }
                i++;
            }
            this.updateBatchById(signList2);
        }

    }

//    public List<StuVo> forDess(List<StuVo> list1){
//        if(list1.size()==0){
//            return new ArrayList<>();
//        }
//        for (int i = 0; i < list1.size(); i++) {
//            list1.get(i).setDes(i+1);
//        }
//        return list1;
//    }

    @Override
    public void downloadStuDecrypt(HttpServletResponse response,String field) throws Exception {
        List<StuDecryptVo> asourVos = new ArrayList<>();
        List<CareStuSignUpComRealityDO> comRealityDOS = this.selectList(new EntityWrapper<CareStuSignUpComRealityDO>().orderBy("record_sort",true));
        if(comRealityDOS.isEmpty()){
            return;
        }
        for (int i = 0; i < comRealityDOS.size(); i++) {
            EncipherDO encipherDO = new EncipherDO();
            encipherDO.setStuId(comRealityDOS.get(i).getId());
            encipherDO.setField(field);
            encipherDO = encipherService.selectOne(encipherDO);
            if(Objects.nonNull(encipherDO)){
                comRealityDOS.get(i).setNum1(encipherDO.getNum1());
                comRealityDOS.get(i).setNum2(encipherDO.getNum2());
            }
        }

        comRealityDOS.forEach(a ->{
            StuDecryptVo stuDecryptVo = new StuDecryptVo();
            try {
                copyProperties(a,stuDecryptVo);
            } catch (Exception e) {
                e.printStackTrace();
            }
            asourVos.add(stuDecryptVo);

        });
        String name = "-";
        switch (field){
            case "A" : name = "指定照护计划选手与一次加密信息";break;
            case "B1" : name = "居家场景选手与一次加密信息";break;
            case "B2" : name = "月子中心场景选手与一次加密信息";break;
            case "C" : name = "职业素养测评选手与一次加密信息";break;
        }
        EasyPoiUtil.exportExcel(asourVos, name, name, StuDecryptVo.class, name, response);
    }

    @Override
    public void downloadStuTeam(HttpServletResponse response,String field) throws Exception{
        List<StuDecryptVo> asourVos = new ArrayList<>();
        Wrapper<CareStuSignUpComRealityDO> wrapper=new EntityWrapper<>();
        //分页查询团队信息
        wrapper.groupBy("unit_name");
        wrapper.orderBy("record_sort",true);
        List<CareStuSignUpComRealityDO>  page1= this.selectList(wrapper);
        //查询所有考生信息
        List<CareStuSignUpComRealityDO> stus = this.selectList(new EntityWrapper<CareStuSignUpComRealityDO>());
        //绑定加密信息
        //根据赛场查询加密数据
        List<EncipherDO> encipherDOS = encipherService.selectList(new EntityWrapper<EncipherDO>().eq("field",field));
        //循环绑定加密信息
        if(!encipherDOS.isEmpty()){
            stus.forEach(a ->encipherDOS.forEach(b  ->{
                if(Objects.equals(a.getId(),b.getStuId())){
                    a.setNum1(b.getNum1());
                    a.setNum2(b.getNum2());
                }
            }));
        }
        //创建返回信息
        List<OperationVo> operationVos = new ArrayList<>();
        if(page1.isEmpty()){
            return;
        }
        //判断赋值
        for (int i = 0; i < page1.size(); i++) {
            OperationVo vo = new OperationVo();
            //给团队字段赋值
            copyProperties(page1.get(i),vo);
            for (int j = 0; j < stus.size(); j++) {
                //绑定考生信息
                if(page1.get(i).getUnitName().equals(stus.get(j).getUnitName())){
                    if(Objects.isNull(vo.getNameOne())){
                        vo.setNameOne(stus.get(j).getName());
                        vo.setOneId(stus.get(j).getId());
                        vo.setOneNum1(stus.get(j).getNum1());
                        continue;
                    }
                    if(Objects.isNull(vo.getNameTwo())){
                        vo.setNameTwo(stus.get(j).getName());
                        vo.setTwoId(stus.get(j).getId());
                        vo.setTwoNum1(stus.get(j).getNum1());
                        continue;
                    }
                }
            }
            operationVos.add(vo);
        }
        EasyPoiUtil.exportExcel(operationVos, "制定照护计划选手与一次加密信息", "制定照护计划选手与一次加密信息", OperationVo.class, "制定照护计划选手与一次加密信息", response);
    }

    @Override
    public Result list(CareStuSignUpComRealityDO stuSignUpComDTO) {
        Wrapper<CareStuSignUpComRealityDO> wrapper=new EntityWrapper<>();
        Page<CareStuSignUpComRealityDO> page = new Page<CareStuSignUpComRealityDO>(stuSignUpComDTO.getCurrent(),stuSignUpComDTO.getSize());
        // 分页查询考生列表数据
        Page<CareStuSignUpComRealityDO> page1 = this.selectPage(page,wrapper);
        //根据赛场查询加密数据
        List<EncipherDO> encipherDOS = encipherService.selectList(new EntityWrapper<EncipherDO>().eq("field",stuSignUpComDTO.getField()));
        //循环绑定加密信息
        if(encipherDOS.isEmpty()){
            return Result.ok(page1);
        }
        page1.getRecords().forEach(a ->encipherDOS.forEach(b  ->{
            if(Objects.equals(a.getId(),b.getStuId())){
                a.setNum1(b.getNum1());
                a.setNum2(b.getNum2());
            }
        }));
        return Result.ok(page1);
    }

    @Override
    public Result teamList(CareStuSignUpComRealityDO stuSignUpComDTO) throws Exception {
        Page<OperationVo> opPage = new Page<OperationVo>(stuSignUpComDTO.getCurrent(),stuSignUpComDTO.getSize());
        Wrapper<CareStuSignUpComRealityDO> wrapper=new EntityWrapper<>();
        Page<CareStuSignUpComRealityDO> page = new Page<CareStuSignUpComRealityDO>(stuSignUpComDTO.getCurrent(),stuSignUpComDTO.getSize());
        //分页查询团队信息
        wrapper.groupBy("unit_name");
        wrapper.orderBy("record_sort",true);
        Page<CareStuSignUpComRealityDO>  page1= this.selectPage(page,wrapper);
        //查询所有考生信息
        List<CareStuSignUpComRealityDO> stus = this.selectList(new EntityWrapper<CareStuSignUpComRealityDO>());
        //绑定加密信息
        //根据赛场查询加密数据
        List<EncipherDO> encipherDOS = encipherService.selectList(new EntityWrapper<EncipherDO>().eq("field",stuSignUpComDTO.getField()));
        //循环绑定加密信息
        if(!encipherDOS.isEmpty()){
            stus.forEach(a ->encipherDOS.forEach(b  ->{
                if(Objects.equals(a.getId(),b.getStuId())){
                    a.setNum1(b.getNum1());
                    a.setNum2(b.getNum2());
                }
            }));
        }

        //创建返回信息
        List<OperationVo> operationVos = new ArrayList<>();
        if(page1.getRecords().isEmpty()){
            return Result.ok(opPage.setRecords(operationVos));
        }
        //判断赋值
        for (int i = 0; i < page1.getRecords().size(); i++) {
            OperationVo vo = new OperationVo();
            //给团队字段赋值
            copyProperties(page1.getRecords().get(i),vo);
            for (int j = 0; j < stus.size(); j++) {
                //绑定考生信息
                if(page1.getRecords().get(i).getUnitName().equals(stus.get(j).getUnitName())){
                    if(Objects.isNull(vo.getNameOne())){
                        vo.setNameOne(stus.get(j).getName());
                        vo.setOneId(stus.get(j).getId());
                        vo.setOneNum1(stus.get(j).getNum1());
                        continue;
                    }
                    if(Objects.isNull(vo.getNameTwo())){
                        vo.setNameTwo(stus.get(j).getName());
                        vo.setTwoId(stus.get(j).getId());
                        vo.setTwoNum1(stus.get(j).getNum1());
                        continue;
                    }
                }
            }
            operationVos.add(vo);
        }
        opPage.setTotal(page1.getTotal());
        return Result.ok(opPage.setRecords(operationVos));
    }


    /**
     * 反射赋值
     * @param source
     * @param target
     * @param <T>
     * @param <S>
     * @return
     * @throws Exception
     */
    public static <T, S> T copyProperties(S source, T target) throws Exception {
        Class<?> sourceClass = source.getClass();
        Class<?> targetClass = target.getClass();

        Field[] sourceFields = sourceClass.getDeclaredFields();
        for (Field sourceField : sourceFields) {
            String fieldName = sourceField.getName();
            Field targetField = null;
            try {
                targetField = targetClass.getDeclaredField(fieldName);
            } catch (NoSuchFieldException e) {
                // 目标对象不存在该属性，忽略
                continue;
            }

            sourceField.setAccessible(true);
            targetField.setAccessible(true);

            Object value = sourceField.get(source);
            targetField.set(target, value);
        }
        return target;
    }

    /** 基本信息统计 */
    @Override
    public Result<?> statisticAnalysis() {
        ExaminationCostStatisticVo resultVO = new ExaminationCostStatisticVo();
        //统计民族分布
        List<String> nationListX = new ArrayList<>();
        List<String> nationListY = new ArrayList<>();
        List<NationVo> nationVos = this.baseMapper.queryCountByNation();
        if(null!=nationVos && !nationVos.isEmpty()){
            for (NationVo nationVo : nationVos) {
                nationListX.add(nationVo.getName());
                nationListY.add(nationVo.getValue());
            }
        }
        resultVO.setNationListX(nationListX);
        resultVO.setNationListY(nationListY);
        //查询性别占比
        resultVO.setSexPercentage(this.baseMapper.queryProportionBySex());
        //年龄统计
        List<String> ageListX = new ArrayList<>();
        List<String> ageListY = new ArrayList<>();
        List<NationVo> nationVos1 = this.baseMapper.queryAgeList();
        resultVO.setAgePercentage(nationVos1);
        if(null!=nationVos1 && !nationVos1.isEmpty()){
            for (NationVo nationVo : nationVos1) {
                ageListX.add(nationVo.getValue());
                ageListY.add(nationVo.getName());
            }
        }
        resultVO.setAgeListX(ageListX);
        resultVO.setAgeListY(ageListY);
        //年龄占比
        ExaminationCostStatisticVo examinationCostStatisticVo = this.baseMapper.queryProportionByAge();
        resultVO.setMaximumAge(examinationCostStatisticVo.getMaximumAge() +"岁");
        resultVO.setMinimumAge(examinationCostStatisticVo.getMinimumAge() +"岁");
        resultVO.setAverageAge(examinationCostStatisticVo.getAverageAge() +"岁");
        //查询省份数量
        resultVO.setTotalProvince(this.baseMapper.queryProvinceCount());
        //查询竞赛总人数
        resultVO.setTotalPeople(this.selectCount(new EntityWrapper<>()));
        //查询参赛院校
        resultVO.setTotalUnitName(this.baseMapper.queryNumByUnitName());

        return Result.ok(resultVO);
    }

    @Override
    public void updateRecordNumber(@Param("list") List<CareStuSignUpComRealityDO> list) {
        this.baseMapper.updateRecordNumber(list);
    }

}
